#ifndef _MB_Slave_H
#define _MB_Slave_H
#include "UART.h"
#include "CRC_16.h"

#define MB_SLAVE   1

#ifndef UART_1
#define UART_1      0
#endif
#ifndef UART_2
#define UART_2      1
#endif
#ifndef UART_3
#define UART_3      2
#endif
#ifndef UART_4
#define UART_4      3
#endif

#ifndef ModBus_Slave_UART
#define ModBus_Slave_UART     UART_1  //从站默认使用串口
#endif

#ifndef ModBus_Id
#define ModBus_Id       1           //从站ID
#endif

// 485控制引脚宏定义
// #define  MB_S_RS485_CONTROL_PIN           P1_0    
// #define  MB_S_RS485_CONTROL_PIN_MODE      {P2M1&=~0x01;P2M0|=0x01;}
#ifndef  MB_S_RS485_CONTROL_SEND_MODE 
#define  MB_S_RS485_CONTROL_SEND_MODE      1  //发送时引脚的电平
#endif

#ifndef S_COIL_NCOILS
#define S_COIL_NCOILS   2000 //线圈数量
#endif

#ifndef S_DISCRETE_INPUT_NDISCRETES
#define S_DISCRETE_INPUT_NDISCRETES   16 //离散量输入数量
#endif

#ifndef S_REG_INPUT_NREGS
#define S_REG_INPUT_NREGS 100 //输入寄存器数量
#endif

#ifndef S_REG_HOLDING_NREGS
#define S_REG_HOLDING_NREGS 100 //保持寄存器数量
#endif

#ifndef  S_COIL_START
#define  S_COIL_START 0  //线圈初始地址
#endif 

#ifndef S_DISCRETE_INPUT_START
#define S_DISCRETE_INPUT_START 0 //离散量初始地址
#endif 


#ifndef  S_REG_INPUT_START
#define  S_REG_INPUT_START 0  //输入寄存器初始地址
#endif 

#ifndef  S_REG_HOLDING_START
#define  S_REG_HOLDING_START 0   //保持寄存器初始地址
#endif 

//校验方式
typedef enum
{
    MB_S_PAR_NONE,      //无校验
    MB_S_PAR_ODD,       //奇校验
    MB_S_PAR_EVEN       //偶校验
} MBSlaveParity;

MBSlaveParity mb_s_Parity; //校验方式
/*
__at(0x0400) xdata uint16 usSRegInBuf[S_REG_INPUT_NREGS]; //输入寄存器缓存
__at(0x0500) xdata uint16 usSRegHoldBuf[S_REG_HOLDING_NREGS];   //保持寄存器缓存
__at(0x0600) xdata uint8 ucSCoilBuf[(S_COIL_NCOILS % 8) ? ((S_COIL_NCOILS / 8) + 1) : (S_COIL_NCOILS / 8)];//线圈缓存
__at(0x0700) xdata uint8 ucSDiscInBuf[(S_DISCRETE_INPUT_NDISCRETES % 8) ? ((S_DISCRETE_INPUT_NDISCRETES / 8) + 1) : (S_DISCRETE_INPUT_NDISCRETES / 8)];//从机离散量

__at(0x0200) xdata uint8 ModBus_temp[256];      //串口临时接收数组
__at(0x0300) xdata uint8 ModBus_data[256];      //校验成功接收到数组
__at(0x0000) xdata uint8 ModBus_Send_data[256]; //发送数组
__at(0x0100) xdata uint8 data_temp[256];        //大数组不能跨页，固定地址
*/

xdata uint16 usSRegInBuf[S_REG_INPUT_NREGS]; //输入寄存器缓存
xdata uint16 usSRegHoldBuf[S_REG_HOLDING_NREGS];   //保持寄存器缓存
xdata uint8 ucSCoilBuf[(S_COIL_NCOILS % 8) ? ((S_COIL_NCOILS / 8) + 1) : (S_COIL_NCOILS / 8)];//线圈缓存
xdata uint8 ucSDiscInBuf[(S_DISCRETE_INPUT_NDISCRETES % 8) ? ((S_DISCRETE_INPUT_NDISCRETES / 8) + 1) : (S_DISCRETE_INPUT_NDISCRETES / 8)];//从机离散量

xdata uint8 ModBus_temp[256];      //串口临时接收数组
xdata uint8 ModBus_data[256];      //校验成功接收到数组
xdata uint8 ModBus_Send_data[256]; //发送数组
xdata uint8 data_temp[256];        //大数组不能跨页，固定地址

//static uint8 ModBus_Id=1;
static uint16 mb_s_send_len;           //发送长度
static uint8 mb_s_rec_len = 0;         //接收长度
static uint8 mb_s_j;                   //临时循环用变量
static xdata uint16 mb_s_crc_temp = 0; // 16位CRC临时变量

static uint32 mb_s_tick = 0;           //时间tick单位0.1ms
static xdata uint32 mb_s_rec_tick = 0; //接收到数据暂存时间值单位0.1ms
static uint8 mb_s_p = 0;        //串口接收到的指针
static uint8 mb_s_rec_timeout = 0;     //超时值一般1.5到2个字
static uint8 mb_s_rec_en = 0;          //接收到数据并CRC检验有效

//modbus从机初始化
void MBSlaveInit(UART_Name uart_n, UART_PIN uart_rx_pin, UART_PIN uart_tx_pin, uint32 baud, UART_TIMN tim_n, MBSlaveParity eParity);
void MBSlavePoll(); //modbus从机轮询函数

/*MR新增的通信回调函数,参数为MODBUS当前接收的功能码*/
typedef void (*MR_CallbackFunc)(uint8);// 回调函数类型定义
// 根据不同的选项设置回调函数
MR_CallbackFunc mr_callback = 0;

int8 MBSlaveGetCoil(uint16 addr); //获取线圈值
int8 MBSlaveSetCoil(uint16 addr,uint8 vol); //设置线圈值
int8 MBSlaveGetDisc(uint16 addr); //获取离散量输入值
int8 MBSlaveSetDisc(uint16 addr,uint8 vol); //设置离散量输入值
uint16 MBSlaveGetInputReg(uint16 addr); //获取输入寄存器值
int8 MBSlaveSetInputReg(uint16 addr,uint16 vol); //设置输入寄存器值
uint16 MBSlaveGetHoldReg(uint16 addr); //获取保持寄存器值
int8 MBSlaveSetHoldReg(uint16 addr,uint16 vol); //设置保持寄存器值
void MBSlaveTimerCallback(); //定时器回调函数，需要每隔100us回调一次

//以下3个函数在内部调用
void MBSlaveSerialInit(UART_Name uart_n, UART_PIN uart_rx_pin, UART_PIN uart_tx_pin, uint32 baud, UART_TIMN tim_n, MBSlaveParity eParity);
void MBSlaveSerialPutBuff(UART_Name uart_n, uint8* p, uint16 len); //串口发送数组
uint8 MBSlaveSerialGetBuff(); //串口接收

//========================================================================
// 描述: 获取线圈值.
// 参数: addr:线圈地址.
// 返回: 线圈值（不在范围内返回-1）.
//========================================================================
int8 MBSlaveGetCoil(uint16 addr)
{
    if ((addr < S_COIL_START) || (addr > (S_COIL_START + S_COIL_NCOILS)))
    {
        return -1;
    }

    if (ucSCoilBuf[(addr - S_COIL_START) / 8] & (1 << ((addr - S_COIL_START) % 8)))
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

//========================================================================
// 描述: 设置线圈值.
// 参数: addr:线圈地址; vol:值（0/1）.
// 返回: 成功返回1.
//========================================================================
int8 MBSlaveSetCoil(uint16 addr,uint8 vol)
{
    if ((addr < S_COIL_START) || (addr > (S_COIL_START + S_COIL_NCOILS)))
    {
        return -1;
    }
    if(vol)
    {
        ucSCoilBuf[(addr - S_COIL_START) / 8]|=(1 << ((addr - S_COIL_START) % 8));

    }else{
        ucSCoilBuf[(addr - S_COIL_START) / 8]&=~(1 << ((addr - S_COIL_START) % 8));

    }
    return 1;
}

//========================================================================
// 描述: 获取离散量输入的值.
// 参数: addr:离散量地址.
// 返回: 成功返回1.
//========================================================================
int8 MBSlaveGetDisc(uint16 addr)
{
    if ((addr < S_DISCRETE_INPUT_START) || (addr > (S_DISCRETE_INPUT_START + S_DISCRETE_INPUT_NDISCRETES)))
    {
        return -1;
    }

    if (ucSDiscInBuf[(addr - S_DISCRETE_INPUT_START) / 8] & (1 << ((addr - S_DISCRETE_INPUT_START) % 8)))
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

//========================================================================
// 描述: 设置离散量输入的值.
// 参数: addr:离散量地址; vol:值（0/1）.
// 返回: 成功返回1.
//========================================================================
int8 MBSlaveSetDisc(uint16 addr,uint8 vol)
{
    if ((addr < S_DISCRETE_INPUT_START) || (addr > (S_DISCRETE_INPUT_START + S_DISCRETE_INPUT_NDISCRETES)))
    {
        return -1;
    }
    if(vol)
    {
        ucSDiscInBuf[(addr - S_DISCRETE_INPUT_START)/8]|=(1 << ((addr - S_DISCRETE_INPUT_START) % 8));

    }else{
        ucSDiscInBuf[(addr - S_DISCRETE_INPUT_START) / 8]&=~(1 << ((addr - S_DISCRETE_INPUT_START) % 8));

    }
    return 1;
}

//========================================================================
// 描述: 获取输入寄存器的值.
// 参数: addr:输入寄存器地址.
// 返回: 成功返回1.
//========================================================================
uint16 MBSlaveGetInputReg(uint16 addr)
{
    if ((addr < S_REG_INPUT_START) || (addr > (S_REG_INPUT_START + S_REG_INPUT_NREGS)))
    {
        return 0;
    }
    return usSRegInBuf[addr - S_REG_INPUT_START];
}

//========================================================================
// 描述: 设置输入寄存器的值.
// 参数: addr:输入寄存器地址; vol:值.
// 返回: 成功返回1.
//========================================================================
int8 MBSlaveSetInputReg(uint16 addr,uint16 vol)
{
    if ((addr < S_REG_INPUT_START) || (addr > (S_REG_INPUT_START + S_REG_INPUT_NREGS)))
    {
        return -1;
    }
    usSRegInBuf[addr - S_REG_INPUT_START] = vol;
    return 1;
}

//========================================================================
// 描述: 获取保持寄存器的值.
// 参数: addr:保持寄存器地址.
// 返回: 成功返回1.
//========================================================================
uint16 MBSlaveGetHoldReg(uint16 addr)
{
    if ((addr < S_REG_HOLDING_START) || (addr > (S_REG_HOLDING_START + S_REG_HOLDING_NREGS)))
    {
        return 0;
    }
    return usSRegHoldBuf[addr - S_REG_HOLDING_START];
}

//========================================================================
// 描述: 设置保持寄存器的值.
// 参数: addr:保持寄存器地址; vol:值.
// 返回: 成功返回1.
//========================================================================
int8 MBSlaveSetHoldReg(uint16 addr,uint16 vol)
{
    if ((addr < S_REG_HOLDING_START) || (addr > (S_REG_HOLDING_START + S_REG_HOLDING_NREGS)))
    {
        return -1;
    }
    usSRegHoldBuf[addr - S_REG_HOLDING_START] = vol;
    return 1;
}

//========================================================================
// 描述: modbus发送函数
// 参数: p: 发送的数组; len:发送多少字节.
// 返回: none.
//========================================================================
void MBSlaveSend(xdata uint8 *p, uint16 len)
{
    uint16 crc16_temp;
    for (mb_s_j = 0; mb_s_j < len; mb_s_j++)
        data_temp[mb_s_j] = p[mb_s_j];
    crc16_temp = CRC16(p, len);
    data_temp[len] = crc16_temp;
    data_temp[len + 1] = (crc16_temp >> 8);
#if defined (MB_S_RS485_CONTROL_PIN)
    MB_S_RS485_CONTROL_PIN = MB_S_RS485_CONTROL_SEND_MODE;
#endif
    // EA = 0;
    MBSlaveSerialPutBuff(ModBus_Slave_UART, data_temp, len + 2); //数组输出
    // EA = 1;
#if defined (MB_S_RS485_CONTROL_PIN)
    MB_S_RS485_CONTROL_PIN = !(MB_S_RS485_CONTROL_SEND_MODE);
#endif
}

//========================================================================
// 描述: modbus接收回调函数（在串口接收中断中调用）
// 参数: none.
// 返回: none.
//========================================================================
void MBSlaveRecvCallback()
{
    if ((mb_s_tick - mb_s_rec_tick > mb_s_rec_timeout) && (mb_s_p != 0))
    {
        for (mb_s_j = 0; mb_s_j < mb_s_p; mb_s_j = mb_s_j + 1)
        {
            ModBus_data[mb_s_j] = ModBus_temp[mb_s_j];
        }
        mb_s_rec_len = mb_s_p;
        mb_s_p = 0;
        mb_s_crc_temp = CRC16(ModBus_data, mb_s_rec_len - 2);
        if ((ModBus_data[mb_s_rec_len - 1] == (mb_s_crc_temp >> 8)) && (ModBus_data[mb_s_rec_len - 2] == (uint8)mb_s_crc_temp) && (ModBus_data[0] == ModBus_Id))
        {
            mb_s_rec_en = 1;
        }
        ModBus_temp[mb_s_p] = MBSlaveSerialGetBuff();
    }
    else
    {
        ModBus_temp[mb_s_p] = MBSlaveSerialGetBuff();
    }
    mb_s_p++;
    mb_s_rec_tick = mb_s_tick;
}

//========================================================================
// 描述: modbus定时器回调函数（在定时器中断中每100us调用一次）
// 参数: none.
// 返回: none.
//========================================================================
void MBSlaveTimerCallback()
{
    mb_s_tick = mb_s_tick + 1;
    if (mb_s_p > 7)
    {
        if (mb_s_tick - mb_s_rec_tick > mb_s_rec_timeout)
        {
            for (mb_s_j = 0; mb_s_j < mb_s_p; mb_s_j = mb_s_j + 1)
            {
                ModBus_data[mb_s_j] = ModBus_temp[mb_s_j];
            }
            mb_s_rec_len = mb_s_p;
            mb_s_p = 0;
            mb_s_crc_temp = CRC16(ModBus_data, mb_s_rec_len - 2);
            if ((ModBus_data[mb_s_rec_len - 1] == (mb_s_crc_temp >> 8)) && (ModBus_data[mb_s_rec_len - 2] == (uint8)mb_s_crc_temp) && (ModBus_data[0] == ModBus_Id))
            {
                mb_s_rec_en = 1;
            }
        }
    }
}

//========================================================================
// 描述: 定时器4初始化函数
// 参数: none.
// 返回: none.
//========================================================================
// void Timer4Init(void) // 100微秒@24.000MHz
// {
//     T4T3M &= 0xdf; //定时器时钟12T模式
//     T4L = 0x38;    //设定定时初值
//     T4H = 0xff;    //设定定时初值
// }

//========================================================================
// 描述: modbus初始化函数
// 参数: uart_n：串口号; uart_rx_pin,uart_tx_pin:引脚; baud:波特率;
//          tim_n:采用的定时器; eParity:校验方式.
// 返回: none.
//========================================================================
void MBSlaveInit(UART_Name uart_n, UART_PIN uart_rx_pin, UART_PIN uart_tx_pin, uint32 baud, UART_TIMN tim_n, MBSlaveParity eParity)
{
#if defined (MB_S_RS485_CONTROL_PIN)
    MB_S_RS485_CONTROL_PIN_MODE
    MB_S_RS485_CONTROL_PIN = !(MB_S_RS485_CONTROL_SEND_MODE);
#endif
    MBSlaveSerialInit(uart_n, uart_rx_pin, uart_tx_pin, baud, tim_n,  eParity);
    // Timer4Init();
    // IE2 |= 0x40;   // 控制定时器中断
    // T4T3M |= 0x80; // 定时器4开始计时
    mb_s_rec_timeout = 200000 / baud;
    mb_s_tick = 0;
    mb_s_rec_tick = 0;
    mb_s_p = 0;
    mb_s_rec_en = 0;
    EA = 1;        // 控制总中断
}

//========================================================================
// 描述: modbus读线圈（01功能码）处理函数（内部调用）
// 参数: none.
// 返回: none.
//========================================================================
static void MBSlave_01()
{
    uint8 k;
    uint16 slen, sadder;
    slen = ModBus_data[mb_s_rec_len - 4] * 256 + ModBus_data[mb_s_rec_len - 3];
    if (slen % 8)
    {
        mb_s_send_len = slen / 8 + 1;
    }
    else
    {
        mb_s_send_len = (slen / 8);
    }

    sadder = ModBus_data[2] * 256 + ModBus_data[3];

    if (sadder < S_COIL_START)
    {
        ModBus_Send_data[0] = ModBus_Id;
        ModBus_Send_data[1] = 0x81;
        ModBus_Send_data[2] = 0x02;
        MBSlaveSend(ModBus_Send_data, 3);
    }
    else if ((sadder + slen) > (S_COIL_START + S_COIL_NCOILS))
    {
        ModBus_Send_data[0] = ModBus_Id;
        ModBus_Send_data[1] = 0x81;
        ModBus_Send_data[2] = 0x03;
        MBSlaveSend(ModBus_Send_data, 3);
    }
    else
    {

        ModBus_Send_data[0] = ModBus_Id;
        ModBus_Send_data[1] = 0x01;
        ModBus_Send_data[2] = mb_s_send_len;
        for (k = 0; k < mb_s_send_len; k++)
        {
            ModBus_Send_data[k + 3] = ucSCoilBuf[(sadder - S_COIL_START) / 8 + k];
        }
        MBSlaveSend(ModBus_Send_data, mb_s_send_len + 3);
    }
}

//========================================================================
// 描述: modbus读离散量输入（02功能码）处理函数（内部调用）
// 参数: none.
// 返回: none.
//========================================================================
static void MBSlave_02()
{

    uint8 k;
    uint16 slen, sadder;
    slen = ModBus_data[mb_s_rec_len - 4] * 256 + ModBus_data[mb_s_rec_len - 3];
    if (slen % 8)
    {
        mb_s_send_len = slen / 8 + 1;
    }
    else
    {
        mb_s_send_len = (slen / 8);
    }

    sadder = ModBus_data[2] * 256 + ModBus_data[3];

    if (sadder < S_DISCRETE_INPUT_START) //地址错误
    {
        ModBus_Send_data[0] = ModBus_Id;
        ModBus_Send_data[1] = 0x82;
        ModBus_Send_data[2] = 0x02;
        MBSlaveSend(ModBus_Send_data, 3);
    }
    else if ((sadder + slen) > (S_DISCRETE_INPUT_START + S_DISCRETE_INPUT_NDISCRETES)) //数据越界
    {
        ModBus_Send_data[0] = ModBus_Id;
        ModBus_Send_data[1] = 0x82;
        ModBus_Send_data[2] = 0x03;
        MBSlaveSend(ModBus_Send_data, 3);
    }
    else
    {
        ModBus_Send_data[0] = ModBus_Id;
        ModBus_Send_data[1] = 0x02;
        ModBus_Send_data[2] = mb_s_send_len;
        for (k = 0; k < mb_s_send_len; k++)
        {
            ModBus_Send_data[k + 3] = ucSDiscInBuf[(sadder - S_DISCRETE_INPUT_START) / 8 + (sadder - S_DISCRETE_INPUT_START) % 8 + k];
        }
        MBSlaveSend(ModBus_Send_data, mb_s_send_len + 3);
    }
}
//========================================================================
// 描述: modbus读保持寄存器（03功能码）处理函数（内部调用）
// 参数: none.
// 返回: none.
//========================================================================
static void MBSlave_03()
{
    uint8 k;
    uint16 sadder;
    mb_s_send_len = ModBus_data[mb_s_rec_len - 3] * 2;
    sadder = ModBus_data[2] * 256 + ModBus_data[3];
    if (sadder < S_REG_HOLDING_START)
    {
        ModBus_Send_data[0] = ModBus_Id;
        ModBus_Send_data[1] = 0x83;
        ModBus_Send_data[2] = 0x02;
        MBSlaveSend(ModBus_Send_data, 3);
    }
    else if ((sadder + mb_s_send_len) > (S_REG_HOLDING_START + (S_REG_HOLDING_NREGS * 2)))
    {
        ModBus_Send_data[0] = ModBus_Id;
        ModBus_Send_data[1] = 0x83;
        ModBus_Send_data[2] = 0x03;
        MBSlaveSend(ModBus_Send_data, 3);
    }
    else
    {

        ModBus_Send_data[0] = ModBus_Id;
        ModBus_Send_data[1] = 0x03;
        ModBus_Send_data[2] = mb_s_send_len;
        for (k = 0; k < (mb_s_send_len / 2); k++)
        {

            ModBus_Send_data[2 * k + 4] = (uint8)usSRegHoldBuf[(sadder - S_REG_HOLDING_START) + k];
            ModBus_Send_data[2 * k + 3] = usSRegHoldBuf[(sadder - S_REG_HOLDING_START) + k] >> 8;
        }
        MBSlaveSend(ModBus_Send_data, mb_s_send_len + 3);
    }
}

//========================================================================
// 描述: modbus读输入寄存器（04功能码）处理函数（内部调用）
// 参数: none.
// 返回: none.
//========================================================================
static void MBSlave_04() //读输入寄存器状态
{

    uint8 k;
    uint16 sadder;
    mb_s_send_len = ModBus_data[mb_s_rec_len - 3] * 2;
    sadder = ModBus_data[2] * 256 + ModBus_data[3];
    if (sadder < S_REG_HOLDING_START)
    {
        ModBus_Send_data[0] = ModBus_Id;
        ModBus_Send_data[1] = 0x84;
        ModBus_Send_data[2] = 0x02;
        MBSlaveSend(ModBus_Send_data, 3);
    }
    else if ((sadder + mb_s_send_len) > (S_REG_INPUT_START + (S_REG_INPUT_NREGS * 2)))
    {
        ModBus_Send_data[0] = ModBus_Id;
        ModBus_Send_data[1] = 0x84;
        ModBus_Send_data[2] = 0x03;
        MBSlaveSend(ModBus_Send_data, 3);
    }
    else
    {

        ModBus_Send_data[0] = ModBus_Id;
        ModBus_Send_data[1] = 0x04;
        ModBus_Send_data[2] = mb_s_send_len;
        for (k = 0; k < (mb_s_send_len / 2); k++)
        {

            ModBus_Send_data[2 * k + 4] = (uint8)usSRegInBuf[(sadder - S_REG_INPUT_START) + k];
            ModBus_Send_data[2 * k + 3] = usSRegInBuf[(sadder - S_REG_INPUT_START) + k] >> 8;
        }
        MBSlaveSend(ModBus_Send_data, mb_s_send_len + 3);
    }
}

//========================================================================
// 描述: modbus写单个线圈（05功能码）处理函数（内部调用）
// 参数: none.
// 返回: none.
//========================================================================
static void MBSlave_05()
{
    uint8 k;
    uint16 sadder = ModBus_data[2] * 256 + ModBus_data[3];
    if (sadder < S_COIL_START || sadder > (S_COIL_START + S_COIL_NCOILS))
    {
        ModBus_Send_data[0] = ModBus_Id;
        ModBus_Send_data[1] = 0x85;
        ModBus_Send_data[2] = 0x02;
        MBSlaveSend(ModBus_Send_data, 3);
    }
    else
    {
        sadder = (sadder - S_COIL_START);
        if (ModBus_data[4])
        {
            ucSCoilBuf[sadder / 8] |= (1 << (sadder % 8));
        }
        else
        {
            ucSCoilBuf[sadder / 8] &= ~(1 << (sadder % 8));
        }

        for (k = 0; k < 8; k++)
            ModBus_Send_data[k] = ModBus_data[k];
        MBSlaveSend(ModBus_Send_data, 6);
    }
}

//========================================================================
// 描述: modbus写单个保持寄存器（06功能码）处理函数（内部调用）
// 参数: none.
// 返回: none.
//========================================================================
static void MBSlave_06()
{
    uint8 k;
    uint16 sadder = ModBus_data[2] * 256 + ModBus_data[3];
    if (sadder < S_REG_HOLDING_START || sadder > (S_REG_HOLDING_START + S_REG_HOLDING_NREGS))
    {
        ModBus_Send_data[0] = ModBus_Id;
        ModBus_Send_data[1] = 0x86;
        ModBus_Send_data[2] = 0x02;
        MBSlaveSend(ModBus_Send_data, 3);
    }
    else
    {
        sadder = (sadder - S_REG_HOLDING_START);
        usSRegHoldBuf[sadder] = ModBus_data[4] * 256 + ModBus_data[5];

        for (k = 0; k < 8; k++)
            ModBus_Send_data[k] = ModBus_data[k];
        MBSlaveSend(ModBus_Send_data, 6);
    }
}

//========================================================================
// 描述: modbus写多个线圈（15功能码）处理函数（内部调用）
// 参数: none.
// 返回: none.
//========================================================================
static void MBSlave_15()
{
    uint8 k;
    uint16 slen, sadder;
    slen = ModBus_data[4] * 256 + ModBus_data[5];
    if (slen % 8)
    {
        mb_s_send_len = slen / 8 + 1;
    }
    else
    {
        mb_s_send_len = (slen / 8);
    }

    sadder = ModBus_data[2] * 256 + ModBus_data[3];

    if (sadder < S_COIL_START)
    {
        ModBus_Send_data[0] = ModBus_Id;
        ModBus_Send_data[1] = 0x8F;
        ModBus_Send_data[2] = 0x02;
        MBSlaveSend(ModBus_Send_data, 3);
    }
    else if ((sadder + slen) > (S_COIL_START + S_COIL_NCOILS))
    {
        ModBus_Send_data[0] = ModBus_Id;
        ModBus_Send_data[1] = 0x8F;
        ModBus_Send_data[2] = 0x03;
        MBSlaveSend(ModBus_Send_data, 3);
    }
    else
    {
        for (k = 0; k < ModBus_data[6]; k++)

            ucSCoilBuf[((sadder - S_COIL_START) / 8) + k] = ModBus_data[7 + k]; //只能以8的倍数为起始地址发送

        for (k = 0; k < 8; k++)
            ModBus_Send_data[k] = ModBus_data[k];
        MBSlaveSend(ModBus_Send_data, 6);
    }
}

//========================================================================
// 描述: modbus写多个保持寄存器（16功能码）处理函数（内部调用）
// 参数: none.
// 返回: none.
//========================================================================
static void MBSlave_16()
{
    uint8 k;
    uint16 sadder;
    mb_s_send_len = ModBus_data[6];
    sadder = ModBus_data[2] * 256 + ModBus_data[3];
    if (sadder < S_REG_HOLDING_START)
    {
        ModBus_Send_data[0] = ModBus_Id;
        ModBus_Send_data[1] = 0x90;
        ModBus_Send_data[2] = 0x02;
        MBSlaveSend(ModBus_Send_data, 3);
    }
    else if ((sadder + mb_s_send_len) > (S_REG_HOLDING_START + (S_REG_HOLDING_NREGS * 2)))
    {
        ModBus_Send_data[0] = ModBus_Id;
        ModBus_Send_data[1] = 0x90;
        ModBus_Send_data[2] = 0x03;
        MBSlaveSend(ModBus_Send_data, 3);
    }
    else
    {
        for (k = 0; k < 8; k++)
            ModBus_Send_data[k] = ModBus_data[k];
        MBSlaveSend(ModBus_Send_data, 6);
    }
    for (k = 0; k < (mb_s_send_len / 2); k++)
    {
        usSRegHoldBuf[sadder - S_REG_HOLDING_START + k] = ModBus_data[7 + 2 * k] * 256 + ModBus_data[8 + 2 * k];
    }
}

// MR新增的通信时调用回调函数
void MR_CallCallback(MR_CallbackFunc callback, int value) {
    if (callback != 0) {
        callback(value);
    }
}
//========================================================================
// 描述: modbus轮询（在主函数中轮询）
// 参数: none.
// 返回: none.
//========================================================================
void MBSlavePoll()
{
    if (mb_s_rec_en)
    {
        mb_s_rec_en = 0;
        if (ModBus_data[1] == 1)
        {
            MBSlave_01();
        }
        if (ModBus_data[1] == 2)
        {
            MBSlave_02();
        }
        if (ModBus_data[1] == 3)
        {
            MBSlave_03();
        }
        if (ModBus_data[1] == 4)
        {
            MBSlave_04();
        }
        if (ModBus_data[1] == 5)
        {
            MBSlave_05();
        }
        if (ModBus_data[1] == 6)
        {
            MBSlave_06();
        }
        if (ModBus_data[1] == 15)
        {
            MBSlave_15();
        }
        if (ModBus_data[1] == 16)
        {
            MBSlave_16();
        }
        // MR新增的调用回调函数
        MR_CallCallback(mr_callback, ModBus_data[1]);
    }
}

//========================================================================
// 描述: 串口初始化，打开串口中断（内部调用）.
// 参数: uart_n:串口号; uart_rx_pin,uart_tx_pin:引脚; baud:波特率; tim_n:定时器;eParity:校验.
// 返回: none.
//========================================================================
void MBSlaveSerialInit(UART_Name uart_n, UART_PIN uart_rx_pin, UART_PIN uart_tx_pin, uint32 baud, UART_TIMN tim_n, MBSlaveParity eParity)
{
    mb_s_Parity = eParity;

    uart_init(uart_n, uart_rx_pin, uart_tx_pin, baud, tim_n);
#if (ModBus_Slave_UART == UART_1)
    ES = 1;	//允许串口1中断
    if( (mb_s_Parity != MB_S_PAR_NONE)&&(uart_n == UART_1) )
    {
        SCON |= 0xC0;   //可变波特率9位数据模式
    }
#endif
#if (ModBus_Slave_UART == UART_2)
    IE2 |= 0x01 << 0;	//允许串口2中断
    if( (mb_s_Parity != MB_S_PAR_NONE)&&(uart_n == UART_2) )
    {
        S2CON |= 0x80;
    }
#endif
#if (ModBus_Slave_UART == UART_3)
    IE2 |= 0x01 << 3;	//允许串口3中断
    if( (mb_s_Parity != MB_S_PAR_NONE)&&(uart_n == UART_3) )
    {
        S3CON |= 0x80; 
    }
#endif
#if (ModBus_Slave_UART == UART_4)
    IE2 |= 0x01 << 4;	//允许串口4中断
    if( (mb_s_Parity != MB_S_PAR_NONE)&&(uart_n == UART_4) )
    {
        S4CON |= 0x80; 
    } 
#endif
    EA = 1; //打开总中断
}

//========================================================================
// 描述: 串口写1字节函数（内部调用）.
// 参数: none.
// 返回: none.
//========================================================================
void MBSlaveSerialPutByte(UART_Name uart_n, uint8 ucByte)
{
    uint8 temp;
#if (ModBus_Slave_UART == UART_1)
    if( (uart_n == UART_1)&&(mb_s_Parity != MB_S_PAR_NONE) )
    {
        ACC = ucByte;
        TB8 = P;
        if(mb_s_Parity == MB_S_PAR_ODD)  //如果为奇校验
        {
            TB8 = !TB8;
        }
    }
#endif
#if (ModBus_Slave_UART == UART_2)
    if( (uart_n == UART_2)&&(mb_s_Parity != MB_S_PAR_NONE) )
    {
        ACC = ucByte;
        temp = P;
        if(mb_s_Parity == MB_S_PAR_ODD)  //如果为奇校验
        {
            temp = !temp;
        }
        if(temp == 1)
        {
            S2CON |= 0X08;
        }else{
            S2CON &= ~0X08;
        }
    }
#endif
#if (ModBus_Slave_UART == UART_3)
    if( (uart_n == UART_3)&&(mb_s_Parity != MB_S_PAR_NONE) )
    {
        ACC = ucByte;
        temp = P;
        if(mb_s_Parity == MB_S_PAR_ODD)  //如果为奇校验
        {
            temp = !temp;
        }
        if(temp == 1)
        {
            S3CON |= 0X08;
        }else{
            S3CON &= ~0X08;
        }
    }
#endif
#if (ModBus_Slave_UART == UART_4)
    if( (uart_n == UART_4)&&(mb_s_Parity != MB_S_PAR_NONE) )
    {
        ACC = ucByte;
        temp = P;
        if(mb_s_Parity == MB_S_PAR_ODD)  //如果为奇校验
        {
            temp = !temp;
        }
        if(temp == 1)
        {
            S4CON |= 0X08;
        }else{
            S4CON &= ~0X08;
        }
    }
#endif
    uart_putchar(uart_n,ucByte);
}

//========================================================================
// 描述: 串口发送数组（内部调用）.
// 参数: none.
// 返回: none.
//========================================================================
void MBSlaveSerialPutBuff(UART_Name uart_n, uint8* p, uint16 len)
{
	while (len--){
        MBSlaveSerialPutByte(uart_n, *p++);
    }	
}

//========================================================================
// 描述: 串口读1字节函数（内部调用）.
// 参数: none.
// 返回: none.
//========================================================================
uint8 MBSlaveSerialGetBuff()
{
    uint8 dat;
    bit uP;
#if (ModBus_Slave_UART == UART_1)
    dat = SBUF;
    if(mb_s_Parity != MB_S_PAR_NONE){
        ACC = dat;
        uP = P;
        if(mb_s_Parity == MB_S_PAR_EVEN)  //如果为偶校验
        {
            uP = !uP;
        }
        if(uP == RB8) //校验失败
        {
            return 0;
        }else{
            return dat;
        }
    }
    return dat;
#endif
#if (ModBus_Slave_UART == UART_2)
    dat = S2BUF;
    if(mb_s_Parity != MB_S_PAR_NONE){
        ACC = dat;
        uP = P;
        if(mb_s_Parity == MB_S_PAR_EVEN)  //如果为偶校验
        {
            uP = !uP;
        }
        if(uP == (S2CON&0x04)) //校验失败
        {
            return 0;
        }else{
            return dat;
        }
    }
    return dat;
#endif
#if (ModBus_Slave_UART == UART_3)
    dat = S3BUF;
    if(mb_s_Parity != MB_S_PAR_NONE){
        ACC = dat;
        uP = P;
        if(mb_s_Parity == MB_S_PAR_EVEN)  //如果为偶校验
        {
            uP = !uP;
        }
        if(uP == (S3CON&0x04)) //校验失败
        {
            return 0;
        }else{
            return dat;
        }
    }
    return dat;
#endif
#if (ModBus_Slave_UART == UART_4)
    dat = S4BUF;
    if(mb_s_Parity != MB_S_PAR_NONE){
        ACC = dat;
        uP = P;
        if(mb_s_Parity == MB_S_PAR_EVEN)  //如果为偶校验
        {
            uP = !uP;
        }
        if(uP == (S4CON&0x04)) //校验失败
        {
            return 0;
        }else{
            return dat;
        }
    }
    return dat;
#endif
}

//========================================================================
// 描述: 定时器4中断函数.
// 参数: none.
// 返回: none.
//========================================================================
// void T_IRQ0(void) interrupt 20 using 3
// {
//     MBSlaveTimerCallback();
// }

//========================================================================
// 描述: 串口中断函数.
// 参数: none.
// 返回: none.
//========================================================================
#if (ModBus_Slave_UART == UART_1)
void MBSlaveUARTInterrupt(void) interrupt 4 using 0
{
    if (UART1_GET_RX_FLAG)
    {
        UART1_CLEAR_RX_FLAG;
        MBSlaveRecvCallback();
    }
}
#endif
#if (ModBus_Slave_UART == UART_2)
void MBSlaveUARTInterrupt(void) interrupt 8 using 0
{
    if (UART2_GET_RX_FLAG)
    {
        UART2_CLEAR_RX_FLAG;
        MBSlaveRecvCallback();
    }
}
#endif
#if (ModBus_Slave_UART == UART_3)
void MBSlaveUARTInterrupt(void) interrupt 17 using 0
{
    if (UART3_GET_RX_FLAG)
    {
        UART3_CLEAR_RX_FLAG;
        MBSlaveRecvCallback();
    }
}
#endif
#if (ModBus_Slave_UART == UART_4)
void MBSlaveUARTInterrupt(void) interrupt 18 using 0
{
    if (UART4_GET_RX_FLAG)
    {
        UART4_CLEAR_RX_FLAG;
        MBSlaveRecvCallback();
    }
}
#endif

#endif